package com.sheng.leetcode.year2023.month04.day23;

import org.junit.Test;

import java.util.Arrays;

/**
 * @author liusheng
 * @date 2023/04/23
 * <p>
 * 1105. 填充书架<p>
 * <p>
 * 给定一个数组 books ，其中 books[i] = [thicknessi, heighti] 表示第 i 本书的厚度和高度。<p>
 * 你也会得到一个整数 shelfWidth 。按顺序 将这些书摆放到总宽度为 shelfWidth 的书架上。<p>
 * 先选几本书放在书架上（它们的厚度之和小于等于书架的宽度 shelfWidth ），<p>
 * 然后再建一层书架。重复这个过程，直到把所有的书都放在书架上。<p>
 * 需要注意的是，在上述过程的每个步骤中，摆放书的顺序与你整理好的顺序相同。<p>
 * 例如，如果这里有 5 本书，那么可能的一种摆放情况是：第一和第二本书放在第一层书架上，<p>
 * 第三本书放在第二层书架上，第四和第五本书放在最后一层书架上。<p>
 * 每一层所摆放的书的最大高度就是这一层书架的层高，书架整体的高度为各层高之和。<p>
 * 以这种方式布置书架，返回书架整体可能的最小高度。<p>
 * <p>
 * 示例 1：<p>
 * 输入：books = [[1,1],[2,3],[2,3],[1,1],[1,1],[1,1],[1,2]], shelfWidth = 4<p>
 * 输出：6<p>
 * 解释：<p>
 * 3 层书架的高度和为 1 + 3 + 2 = 6 。<p>
 * 第 2 本书不必放在第一层书架上。<p>
 * <p>
 * 示例 2:<p>
 * 输入: books = [[1,3],[2,4],[3,2]], shelfWidth = 6<p>
 * 输出: 4<p>
 * <p>
 * 提示：<p>
 * 1 <= books.length <= 1000<p>
 * 1 <= thicknessi <= shelfWidth <= 1000<p>
 * 1 <= heighti <= 1000<p>
 * <p>
 * 来源：力扣（LeetCode）<p>
 * 链接：<a href="https://leetcode.cn/problems/filling-bookcase-shelves">1105. 填充书架</a><p>
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。<p>
 */
public class LeetCode1105 {

    @Test
    public void test01() {
        int[][] books = {{1, 1}, {2, 3}, {2, 3}, {1, 1}, {1, 1}, {1, 1}, {1, 2}};
        int shelfWidth = 4;
//        int[][] books = {{1, 3}, {2, 4}, {3, 2}};
//        int shelfWidth = 6;
        System.out.println(new Solution().minHeightShelves(books, shelfWidth));
    }
}

class Solution {
    public int minHeightShelves(int[][] books, int shelfWidth) {
        int n = books.length;
        // dp[i] 表示前 i 本书的最小高度
        int[] dp = new int[n + 1];
        Arrays.fill(dp, 1000000);
        dp[0] = 0;
        for (int i = 1; i <= n; i++) {
            // w 为最后一本书的宽度，h 为最后一本书的高度
            int w = books[i - 1][0], h = books[i - 1][1];
            // 如果这本书单独摆放在新的一层，那么当前高度直接加上之前的高度即可
            dp[i] = dp[i - 1] + h;
            // 判断是否要加到同一层
            for (int j = i - 1; j > 0; j--) {
                // 循环向前，加上每本书的宽度
                w += books[j - 1][0];
                // 当宽度大于书架的总宽度时退出
                if (w > shelfWidth) {
                    break;
                }
                // 更新当前层的最大高度
                h = Math.max(h, books[j - 1][1]);
                dp[i] = Math.min(dp[i], dp[j - 1] + h);
            }
        }
        return dp[n];
    }
}
